<?php
/**
 * デバッグ用基底クラス
 * jQuery依存
 *
 * @author tanaka
 * @package Controller_Plugin_Debug
 * @subpackage Abstract
 */
abstract class Controller_Plugin_DebugAbstract extends Zend_Controller_Plugin_Abstract
{
	/**
	 * 本体のID属性プレフィックス
	 * @var string
	 */
	private static $_wrapIdPrefix = 'DebugWrap';

	/**
	 * スイッチのID属性プレフィックス
	 * @var string
	 */
	private static $_switchIdPrefix = 'DebugSwitch';

	/**
	 * 本体のクラス属性
	 * @var string
	 */
	private static $_wrapClass = 'DevelDebugWrap';

	/**
	 * スイッチのクラス属性
	 * @var string
	 */
	private static $_switchClass = 'DevelDebugSwitch';

	/**
	 * 有効かどうか
	 * @var bool
	 */
	protected static $_isEnabled = false;

	/**
	 * Controller_Plugin_DebugAbstractの表示数
	 *
	 * @var int
	 */
	private static $_showNumbers = 0;

	/**
	 * Controller_Plugin_DebugAbstractのインスタンス数
	 *
	 * @var int
	 */
	private static $_numberOfInstance = 0;

	/**
	 * パディングのベース
	 * @var int
	 */
	private static $_switchPaddingBase = 16;

	/**
	 * style属性の記述が終了したか
	 * @var bool
	 */
	private static $_isFinishWriteStyle = false;

	/**
	 * DivのID要素
	 * @var string
	 */
	protected $_wrapId;

	/**
	 * スイッチのID要素
	 * @var string
	 */
	protected $_switchId;

	/**
	 * スイッチの場所
	 * @var int
	 */
	protected $_switchPositionPx = 0;

	/**
	 * スイッチカラー
	 * @var string
	 */
	protected $_switchColor = '#FF00FF';

	/**
	 * 有効化、または無効化
	 * @param bool $isEnable
	 * @return
	 */
	public static function changeEnable($isEnable)
	{
		self::$_isEnabled = $isEnable;
	}

	/**
	 * コンストラクタ
	 *
	 * @return void
	 */
	public function __construct()
	{
		$debugPluginName = preg_replace('/.*_([a-zA-Z]+)$/', '$1', get_called_class());

		$this->_wrapId = self::$_wrapIdPrefix . $debugPluginName . self::$_numberOfInstance;
		$this->_switchId = self::$_switchIdPrefix . $debugPluginName . self::$_numberOfInstance;
		self::$_numberOfInstance++;
	}

	/**
	 * 表示用文字列の作成
	 *
	 * @return string
	 */
	abstract protected function _getHtml();

	/**
	 * var_dumpと同様の内容を文字列として受け取ります
	 *
	 * @param mixed $obj
	 * @return string
	 */
	final protected function _dumpString($obj)
	{
		ob_start();
		var_dump($obj);
		$ret = ob_get_contents();
		ob_end_clean();

		return trim($ret);
	}

	/**
	 * Headに書くCSS文字列を返します。
	 *
	 * @return
	 */
	final protected function _getHeadStyle()
	{
		if (self::$_isFinishWriteStyle) return '';

		self::$_isFinishWriteStyle = true;

		return '
			<style type="text/css" media="screen">
				.' .
			self::$_switchClass . '{
					padding: 0pt;
					margin: 0pt;
					position: absolute;
					top: 0pt;
					width: 15px;
					height: 15px;
				}
				
				.' .
			self::$_wrapClass . ' span
				{
					font-size:9pt;
				}
				
				.' .
			self::$_wrapClass . '{
					background-color:#fff;
					color:#333;
					border:1px solid #888;
					padding:8px;
					margin:15px;
					display:none;
					position:absolute;
					top:0;
					left:0;
				}
				
				.' .
			self::$_wrapClass . ' table
				{
					border-collapse: collapse;
					empty-cells: show;
				}
				
				.' .
			self::$_wrapClass . ' th
				{
					background-color: #000;
					color: #fff;
				}
				
				.' .
			self::$_wrapClass . ' td
				{
					background-color: #fff;
					color: #000;
					padding:4px;
				}
				
				.' .
			self::$_wrapClass . ' th, .' . self::$_wrapClass . ' td
				{
					border:1px solid #ccc;
					width: auto;
					height: auto;
					font-family:monospace;
					font-size:9pt;
				}
			</style>
		';
	}

	/**
	 * スイッチの属性値を返します。
	 *
	 * @return string
	 */
	final protected function _getAttributeSwitch()
	{
		return '
			id="' .
			$this->_switchId . '"
			class="' .
			self::$_switchClass . '"
			style="
				background-color: ' .
			$this->_switchColor . ';
				left:' .
			self::$_showNumbers * self::$_switchPaddingBase . 'px;
			" ';
	}

	/**
	 * 本体の属性値を返します。
	 *
	 * @return
	 */
	final protected function _getAttributeWrap()
	{
		return ' id="' . $this->_wrapId . '"
		class="' .
			self::$_wrapClass . '" ';
	}

	/**
	 * ディスパッチループ終了
	 * @return	void
	 */
	public function dispatchLoopShutdown()
	{
		if (!self::$_isEnabled) {
			return;
		}

		$html = $this->_getHtml();
		if (strlen($html) == 0) return;

		$out = '
<script type="text/javascript">
if(window.$)
{
	$(function(){
		$("#' . $this->_switchId . '").click(function(){
			$(".'. self::$_wrapClass . ':visible").not("#' . $this->_wrapId . '").each(function(){
				$(this).hide("fast");
			});
			
			$("#' . $this->_wrapId . '").toggle("fast");
		});
	});
}
</script>

<div ' .
			$this->_getAttributeSwitch() . '></div>
<div ' .
			$this->_getAttributeWrap() . '>' . $html . '</div>';

		//body要素にDebug文字列を埋め込む
		$response = $this->getResponse();
		$body = $response->getBody();
		$body = preg_replace('/<\/body>/', $out . '</body>', $body, 1);

		// styleの埋込み
		$style = $this->_getHeadStyle();
		if (strlen($style) != 0) {
			$body = preg_replace('/<\/head>/', $style . '</head>', $body, 1);
		}

		$response->setBody($body);
		self::$_showNumbers++;
	}

}
